/***************************************************************************
 *   oboe.utils.Benchmark                                                  *
 *   Copyright (C) 2011 by Felipe Manga                                    *
 *   lufeboma@gmail.com                                                    *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/

package oboe.utils
{
	import flash.utils.getTimer;
	
	import oboe.core.Controller;
	
	public class Benchmark extends Controller
	{
		private var tests:Vector.<Test>;
		private var currentTest:int;
		private var maxCycles:int;
		private var currentCycle:int;
		private var done:Boolean;
		
		public function Benchmark( cycles:int )
		{
			super();
			
			currentCycle = 0;
			this.maxCycles = cycles;
			tests = new Vector.<Test>();
			done = false;
		}
		
		public function addTest( name:String, func:Function ):void
		{
			tests.push( new Test(name, func) );
		}
		
		public function printResults():void
		{
			var min:int = 0x7FFFFF;
			var acc:int = 0;
			var test:Test;
			for each( test in this.tests )
			{
				min = Math.min( min, test.score );
				acc += test.score;
			}
			
			for each( test in this.tests )
			{
				trace(
					test.name, ": ",
					"\toverall %:", Math.round( (test.score / acc)*10000 )/100,
					"\t\trelative %:", Math.round( (test.score / min)*10000 )/100
					);
			}
		}
		
		public function slot_onTick( time:Number ):void
		{
			if( currentCycle >= maxCycles )
			{
				if( !done )	printResults();
				done = true;
				this.selfDestruct();
				return;
			}
			var begin:int = getTimer();
			
			this.tests[ this.currentTest ].func();
			
			var end:int = getTimer();
			this.tests[ currentTest ].score += end - begin;
			
			currentTest++;
			if( currentTest == tests.length )
			{
				currentTest = 0;
				currentCycle++;
			}
		}
	}
}

class Test
{
	public var name:String;
	public var score:int;
	public var func:Function;
	public function Test( name:String, func:Function )
	{
		this.name = name;
		this.func = func;
		this.score = 0;
	}
}	
	